\documentclass{article}
\usepackage[UTF8]{ctex} % 用于中文支持
\usepackage{amsmath} % 用于数学公式
\usepackage{enumitem} % 用于列表控制
\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} % 调整页边距

\title{操作系统第一次作业}
\author{计试2301 程远}
\date{}

\begin{document}

\maketitle

\section*{3.1 论述长期调度、中期调度和短期调度的差异}

\textbf{长期调度：}
目标：控制进入就绪队列的进程数量，即决定哪些程序可以被接纳为进程并进入内存。它负责平衡I/O密集型进程和CPU密集型进程的比例，以优化系统整体性能（即保持多道程序度）。
触发频率：非常低。通常在一个进程终止并离开系统时，才会被调用一次。
操作对象：从磁盘上的进程池（作业池）中选择进程，并将其加载到内存中，使其变为就绪状态。

\textbf{中期调度：}
目标：通过引入挂起状态，减轻系统在多道程序度过高时的内存压力。它负责进行进程的换出和换入操作。
触发频率：中等。在系统内存紧张时被触发。
操作对象：将内存中处于阻塞或就绪状态的进程换出到磁盘的挂起队列，并在适当的时候将挂起的进程重新换入内存。

\textbf{短期调度：}
目标：从内存中的就绪队列里选择一个进程，并将CPU分配给它执行。这是最核心、最频繁的调度。
触发频率：非常高。通常在几十到几百毫秒就会发生一次。由时钟中断、I/O中断或进程终止等事件触发。
操作对象：内存中处于就绪状态的进程。

总而言之，调度频率上来说，长期调度 $\ll$ 中期调度 $\ll$ 短期调度。
主要关注点上，长期调度关注程序到进程的转换和系统负载平衡；中期调度关注内存管理；短期调度关注CPU时间的微观分配。

\section*{3.2 内核采取一些动作以便在两个进程之间进行上下文切换，请描述一下}

\textbf{触发中断或系统调用：} 上下文切换通常由以下事件触发：时钟中断（时间片用完）、I/O请求使运行态进程变为阻塞态、进程主动终止或放弃CPU（如调用 \texttt{yield()}）。

\textbf{保存当前进程的上下文：} CPU的控制权从当前运行的进程转移到内核的中断处理程序。内核将当前进程的硬件状态（即上下文）保存到其进程控制块(PCB)中。这包括程序计数器(PC)和程序状态字(PSW)、通用寄存器的值、栈指针、内存管理信息（如页表基地址寄存器）等。

\textbf{更新进程状态：} 内核将当前进程的PCB状态从"运行"修改为"就绪"、"阻塞"或其他相应状态，并将其移动到对应的队列（如就绪队列、设备等待队列）。

\textbf{选择下一个要运行的进程：} 短期调度器从就绪队列中根据特定的调度算法（如FCFS、轮转法、优先级调度等）选择一个进程。

\textbf{恢复下一个进程的上下文：} 内核将选中进程的PCB中保存的上下文信息加载到CPU的相应寄存器中。这包括恢复程序计数器(PC)从而跳转到该进程上次被中断的代码地址、恢复栈指针和通用寄存器、恢复内存管理信息并切换地址空间（如果进程不同）。

\textbf{更新内核数据结构：} 更新当前运行进程的指针，使其指向新调度的进程。

\textbf{切换地址空间：} 如果新旧进程属于不同的用户地址空间（在现代操作系统中很常见），则需要切换页表或段表，并清空TLB以确保内存隔离。

\textbf{跳转执行：} 完成上述所有步骤后，CPU开始执行新恢复的进程的指令。

\section*{3.3 给出Scheduler()和Interrupt()原语的处理流程}

\subsection*{1. Interrupt() 原语处理流程}

\textbf{硬件处理阶段}

中断发生：硬件（如时钟、I/O控制器）或软件（如系统调用指令）产生中断信号。

结束当前指令：CPU完成当前指令的执行。

检测中断：CPU在指令周期的末尾检查是否有未被屏蔽的中断请求。

保存现场：硬件自动完成以下动作：将当前程序计数器(PC)和程序状态字(PSW)等关键信息压入内核栈（通常是当前进程的内核栈，而非用户栈）；关中断，防止在处理当前中断时被新的同级或低级中断打断。

转入中断处理程序：硬件根据中断类型号，查询中断向量表，加载对应中断处理程序的入口地址到PC，开始执行内核的中断处理代码。

\textbf{软件处理阶段}

保存剩余上下文：中断处理程序（通常是汇编代码）继续将其他所有通用寄存器的状态保存到当前进程的PCB或内核栈中。

识别中断源并处理：通过读取相关状态寄存器，确定具体的中断原因（例如，是哪个设备产生的中断），并执行相应的服务例程（如将键盘输入数据复制到缓冲区）。

可能引起调度：如果中断处理导致某个高优先级进程变为就绪（例如，I/O操作完成唤醒了一个等待该I/O的进程），或者当前进程的时间片用完，则可能需要调用 \texttt{Scheduler()}。设置一个内部标志（如 \texttt{need\_resched}）来表明需要重新调度。

恢复上下文并返回：如果不需要调度，则从中断返回。中断处理程序从内核栈或PCB中恢复之前保存的通用寄存器。执行一条特殊的中断返回指令(如 x86 的 \texttt{IRET})。该指令会从内核栈中弹出之前由硬件保存的PSW和PC，从而恢复到被中断的用户进程继续执行。如果需要调度，则不会直接返回，而是先执行 \texttt{Scheduler()}。

\subsection*{2. Scheduler() 原语处理流程}

\texttt{Scheduler()} 是操作系统内核中的一个核心函数，负责选择下一个要运行的进程。它通常在中断或系统调用处理末尾被调用。

\textbf{调用时机：} 在 \texttt{Interrupt()} 或系统调用处理流程的末尾，如果检测到 \texttt{need\_resched} 标志被设置。或者由进程主动调用（如通过 \texttt{sched\_yield()}）。

\textbf{禁止中断：} 在开始调度决策前，通常会暂时禁止中断，以防止在修改关键内核数据结构（如就绪队列）时发生竞态条件。

\textbf{选择进程：} 短期调度算法（如优先级比较、时间片轮转等）被应用于就绪队列，选择一个最适合运行的进程。

\textbf{执行上下文切换：} 调用底层函数执行具体的切换操作。此函数通常用汇编语言编写以实现最高效率。保存当前进程的完整上下文（所有CPU状态）到其PCB中。更新当前进程的PCB状态为"就绪"或其他状态。将"当前运行进程"指针指向新选中的进程。从新进程的PCB中恢复其完整的上下文到CPU寄存器。（可选）切换地址空间（切换页表，清空TLB）。

\textbf{恢复中断并返回：} 上下文切换函数执行完毕后，CPU实际上已经在新进程的内核上下文中运行了。\newline\texttt{Scheduler()} 函数恢复中断使能。当 \texttt{Scheduler()} 函数返回时，它不是返回到调用它的原进程的代码，而是返回到新进程上次被中断或系统调用时在内核中的位置。

\textbf{恢复用户执行：} 随后，内核会执行与 \texttt{Interrupt()} 返回时类似的操作（如执行 \texttt{IRET} 指令），将控制权交还给新进程的用户空间程序，新进程得以继续执行。

\section*{3.4 fork()和exec()}

\textbf{整体控制流程}：父进程打印菜单并读取 \texttt{choice} \(\rightarrow\) \texttt{fork()} 创建子进程 \(\rightarrow\) 父进程进入 \texttt{waitpid(pid\newline\&status,0)} 阻塞等待 \(\rightarrow\) 子进程根据分支使用不同的 \texttt{exec*} 变体执行外部程序；若 \texttt{exec} 成功则\emph{不会返回}，若失败则打印错误并以非零码退出；
父进程在 \texttt{waitpid} 返回后通过 \texttt{WIFEXITED}/\texttt{WEXITSTATUS} 与 \texttt{WIFSIGNALED}/\newline\texttt{WTERMSIG} 判定子进程结束状态并报告。

\textbf{子进程分支与 \texttt{exec()} 变体的选择}：为展示不同调用形态，代码有意分别使用三种 \texttt{exec*}：
\begin{itemize}
  \item \texttt{execl("/bin/ls","ls","-l",NULL)}：\emph{l-List} 形态，参数以可变参数表列出，路径显式给出，适合固定参数的简单命令。
  \item \texttt{execvp("/bin/cat", args)}：\emph{v-Vector} 形态，参数通过 \texttt{argv} 数组传递；\emph{p-Path} 版本通常可按 \texttt{PATH} 搜索（本实现给了绝对路径，同样有效），便于把用户输入的文件名安全地放入 \texttt{argv}。
  \item \texttt{execle("/bin/mkdir","mkdir",dirname,NULL,env)}：\emph{e-Env} 形态，显式传入环境变量指针数组 \texttt{env}；用于演示\textbf{在不污染父进程环境}的前提下为目标程序提供最小可用环境（如仅含 \texttt{PATH}）。
\end{itemize}

\textbf{交互与健壮性}：菜单选择在父进程完成，进入子进程后才根据分支（\texttt{case 2/3}）继续向用户索取\textbf{特定参数}（文件名/目录名），这样可避免父子进程同时读 \texttt{stdin} 的竞争；所有外部程序通过 \texttt{exec} 直接执行，\emph{不使用 \texttt{system()}}，更安全、可控。为防止资源泄漏与僵尸进程，父进程\emph{必须}使用 \texttt{waitpid} 回收；子进程一旦 \texttt{exec} 失败即时以非零码退出，便于父进程准确获知失败原因。

\textbf{可扩展要点（与本实现保持兼容）}：若需\emph{重定向或管道}，可在 \texttt{fork()} 与 \texttt{exec()} 之间对子进程调用 \texttt{dup2()} 重定向 \texttt{stdin/stdout/stderr}；若要\emph{并行处理多请求}，父进程可以在循环中多次 \texttt{fork()}，或切换到基于 I/O 复用/线程池的并发模型；若要\emph{跨平台更友好}，\texttt{execvp} 更适合与 \texttt{PATH} 协作（同时保留显式绝对路径作后备）。整体而言，本实现已覆盖 \texttt{exec} 的三种常用形态（参数列表/参数向量/自定义环境）与父子进程的典型协作模式，满足题目“\texttt{fork()} 创建子进程，\texttt{exec()} 执行独立程序，场景自设”的要求。:contentReference[oaicite:0]{index=0}


\section*{3.5 英汉互译词典}

\textbf{程序设计思路（\texttt{server.py}/与\texttt{client.py}）}\\
架构：TCP C/S、逐行文本协议（UTF-8）。客户端每次发送一行，服务端返回一行并换行。\\
请求：\verb|<direction> <query>\n|，\verb|<direction>| 为 \verb|en|/\verb|zh|（缺省可 AUTO：ASCII→英→汉，否则汉→英）。\\
响应：命中 \verb|OK <translation>|；未命中 \verb|NOTFOUND|；异常 \verb|ERROR <msg>|。\\
词库：默认“内存 Map”（启动加载 JSON/CSV），可选切换到“SQLite+FTS5”（支持前缀/模糊）。\\
并发：课堂规模用每连接一线程/协程即可；开启 \verb|SO_REUSEADDR|、设置读写超时并做异常保护。\\
可观测：记录查询时间、方向、命中状态与耗时，便于后续做 LRU 热词缓存与调优。

\textbf{通过 Tailscale 通信（macOS＋Windows）}\\
两机安装并登录同一 Tailscale 账号（或加入同一 tailnet），在客户端面板查看彼此的 \textbf{100.x.y.z} 地址。\\
服务端为mac端，运行：
\begin{verbatim}
python server.py --host 0.0.0.0 --port 5555
\end{verbatim}
客户端为windows端，用服务端的 100.x 地址连接：
\begin{verbatim}
python client.py 100.86.18.4 5555
\end{verbatim}

\textbf{“更好的方式”与对比}\\
A. \emph{内存 Map（当前默认）}：最简单、查询近似 \(O(1)\)、零依赖；但不持久，不擅长模糊/前缀，大词表占内存。\\
B. \emph{\underline{SQLite + 索引（推荐）}}：单文件、零运维；可开 FTS5 做前缀/模糊，开启 WAL 并发读稳；高并发写较弱，需初始化建表/索引。\\
最小可用 SQL：
\begin{verbatim}
CREATE TABLE dict(
  word TEXT PRIMARY KEY, pos TEXT, phonetic TEXT,
  meaning TEXT, examples TEXT
);
CREATE INDEX idx_word ON dict(word);
-- 可选：全文检索
CREATE VIRTUAL TABLE dict_fts USING fts5(word, meaning, examples);
\end{verbatim}
C. \emph{本地词库 + 翻译API兜底}：覆盖长尾强；本地命中→FTS 模糊候选→API 兜底→写回“缓存表”（含来源/时间戳）；需注意费用/限流/合规与网络可用性。\\
D. \emph{Redis 缓存（可选增强）}：多进程共享、极低延迟热词；但占内存、需守护进程，模糊能力需上层配合。

\end{document}